package com.biz.primus.ms.commodity.service.backend;

import com.biz.primus.base.enums.vendor.VendorType;
import com.biz.primus.base.vo.commodity.ProductIdxIdentityVo;
import com.biz.primus.commodity.vo.CategoryProductSalesTopVo;
import com.biz.primus.commodity.vo.backend.ProductSalesVo;
import com.biz.primus.common.utils.JsonUtils;
import com.biz.primus.ms.base.service.AbstractBaseService;
import com.biz.primus.ms.commodity.dao.po.Product;
import com.biz.primus.ms.commodity.dao.po.ProductStatistic;
import com.biz.primus.ms.commodity.dao.redis.CategoryRedisDao;
import com.biz.primus.ms.commodity.dao.redis.ProductRedisDao;
import com.biz.primus.ms.commodity.dao.repository.product.ProductRepository;
import com.biz.primus.ms.commodity.dao.repository.productstatistic.ProductStatisticRepository;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 商品统计Service实现
 *
 * @author david-liu
 * @date 2017年02月28日
 * @reviewer
 */
@Slf4j
@Service
public class ProductStatisticService extends AbstractBaseService {


    @Autowired
    private ProductStatisticRepository productStatisticRepository;

    @Autowired
    private ProductRedisDao productRedisDao;

    //todo:nan
//    @Autowired
//    private MessageService messageService;

    @Autowired
    private CategoryRedisDao categoryRedisDao;

    @Autowired
    private ProductRepository productRepository;

    @Transactional
    public void updateProductStatistic(List<ProductSalesVo> salesVoList) {
        if (CollectionUtils.isEmpty(salesVoList)) {
            log.info("salesVoList is empty, do nothing.");
            return;
        }
        List<Long> productIds = Lists.newArrayList();
        Map<Long, ProductSalesVo> productSalesVoMap = Maps.newHashMap();
        List<String> productCodes = Lists.newArrayList();
        List<Integer> quantity = Lists.newArrayList();
        for (ProductSalesVo vo : salesVoList) {
            productIds.add(vo.getProductId());
            productSalesVoMap.put(vo.getProductId(), vo);
            productCodes.add(vo.getProductCode());
            if (vo.getQuantity() == null) {
                log.info("ProductSalesVo quantity is null !,set 0");
                quantity.add(0);
            } else {
                quantity.add(vo.getQuantity().intValue());
            }
        }

        List<Product> productList = productRepository.findAll(productIds);
        List<ProductStatistic> statistics = Lists.newArrayList();
        for (Product product : productList) {
            ProductStatistic productStatistic = product.getProductStatistic();
            if (productStatistic == null){
                productStatistic = new ProductStatistic();
                productStatistic.setProduct(product);
                productStatistic.setId(idService.getNextId());
            }
            statistics.add(productStatistic);
        }

        if (CollectionUtils.isNotEmpty(statistics)) {
            synchronized (ProductStatisticService.class) {
                for (ProductStatistic statistic : statistics) {
                    ProductSalesVo vo = productSalesVoMap.get(statistic.getProduct().getId());
                    if (vo != null) {
                        Integer saleCount = statistic.getTotalSalesVolume() == null ? 0 : statistic.getTotalSalesVolume();
                        if (vo.getQuantity() != null) {
                            saleCount = saleCount + vo.getQuantity().intValue();
                        }
                        statistic.setTotalSalesVolume(saleCount);
                    }
                }
                productStatisticRepository.save(statistics);
            }

            productRedisDao.incrSalesVolume(productCodes, quantity);

            for (String productCode : productCodes) {
//                因商品销量改变 更新该productCode 对应的所有索引信息
                ProductIdxIdentityVo vo = new ProductIdxIdentityVo();
                vo.setProductCode(productCode);
//                todo:传入商品类型
                if (productCode.length() < 10) {
                    vo.setProductType(VendorType.TYPE_B.getValue());
                } else {
                    vo.setProductType(VendorType.TYPE_A.getValue());
                }
//                messageService.sendMessage(BizBaseQueue.MQ_SEARCH_PRODUCT_QUEUE, SimpleBizMessage.newMessage(vo));
            }
        }
    }

    /**
     * 计算分类热销商品 topN
     *
     * @param topN
     * @param productSalesVos
     */
    @Transactional
    public void caluCategorySalesTopN(final int topN, List<ProductSalesVo> productSalesVos) {
//      遍历productSalesVos,获取分类集合
        log.debug("统计各分类销量前{} 的商品数据", topN);
        Set<Long> categoryIdSet = new HashSet<>();
        for (ProductSalesVo productSalesVo : productSalesVos) {
            categoryIdSet.add(productSalesVo.getCategoryId());
        }
//        遍历categoryIdSet ,获取对应分类的商品集合,排序,选取topN,存Redis
        final List<CategoryProductSalesTopVo> lists = Lists.newArrayList();
        for (Long categoryId : categoryIdSet) {
            CategoryProductSalesTopVo cat = new CategoryProductSalesTopVo();
            cat.setCategoryId(categoryId);
            List<ProductSalesVo> tmpSalesVo = Lists.newArrayList();
            for (ProductSalesVo productSalesVo : productSalesVos) {
                if (Objects.equals(productSalesVo.getCategoryId(), categoryId)) {
                    tmpSalesVo.add(productSalesVo);
                }
            }
            cat.setProductSalesVos(tmpSalesVo);
            lists.add(cat);
        }
        if (CollectionUtils.isNotEmpty(lists)) {
            log.debug("更新的分类topN数据 {}", JsonUtils.obj2Json(lists));
        }
        this.delayer.executeAfterTransactionCommit(()->{
            log.debug("开始更新redis中销量数据");
            categoryRedisDao.setCategorySalesTopN(lists);
            log.debug("更新完毕");
        });
    }

}
